<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>

    function Cat(name, color) {
        // {}
        // {}[[Prototype]] = Cat.prototype;
        // this -> {}

        // 我们要做的操作 -> 把属性和方法绑定到构造函数的实例化对象中
        this.name = name;
        this.color = color;

        // return this;
    }

    // 原型对象 -> Cat.prototype
    Cat.prototype.species = "Cat";
    Cat.prototype.call = function () {
        console.log("喵喵");
    };
    Cat.prototype.skill = function () {
        console.log("捉老鼠");
    };
    Cat.prototype.say = function () {
        // this指向谁?  调用此方法的实例化对象
        console.log("this指向:", this);
        console.log(this.name, this.color);
    }


    // 给Object的原型对象加属性
    Object.prototype.a = 1;
    Object.prototype.b = 2;


    // console.dir(Cat); //打印对象的属性和方法

    // 实例化对象都有一个原型属性[[Prototype]] 指向创建它的构造函数的原型对象


    // 实例化对象的属性和方法的链式查找机制:
    // 1. 先找实例化对象本身  => 自己有就找自己的
    // 2. 实例化对象本身没有就顺着原型属性[[Prototype]] ->找创建它的构造函数的原型对象 (Cat.prototype)
    // 3. 如果原型对象Cat.prototype上没有要找的方法 => 去Object.prototype上找
    // 4. 如果Object.prototype上没有要找的方法

    // 顺着原型属性[[Prototype]]依次向后查找 -> 原型链

    var Tom = new Cat("Tom", "black");
    console.log(Tom);

    // 1. 先找实例化对象本身  => 自己有就找自己的
    // console.log("找实例化对象本身:", Tom.name, Tom.color);


    // 2. 实例化对象本身没有就顺着原型属性[[Prototype]] ->找创建它的构造函数的原型对象 (Cat.prototype)
    // console.log("找Cat.prototype:", Tom.species);
    // console.log("找Cat.prototype:", Tom.call);
    // console.log("找Cat.prototype:", Tom.skill);
    // console.log("找Cat.prototype:", Tom.say);


    // 3. 如果原型对象Cat.prototype上没有要找的方法 =>去哪找?  去Object.prototype上找
    // 分析: 原型对象本身是一个对象(实例化对象) (Cat.prototype = {constructor: ƒ}),也是构造函数创建的 => 是哪个构造创建的?    => 官方的纯对象数据 => 上级构造函数Object创建的
    // console.log(Cat.prototype);

    // 证明一下 => 获取Cat.prototype的原型属性[[Prototype]] 判断是否指向 Object.prototype

    // console.log(Cat.prototype.__proto__ === Object.prototype); // true
    // console.log(Object.getPrototypeOf(Cat.prototype) === Object.prototype); // true

    // 测试
    // console.log(Tom.toString());  // "[object Object]"
    // console.log(Tom.a);  // "[object Object]"
    // console.log(Tom.b);  // "[object Object]"


    // 4. 如果Object.prototype上没有要找的方法 => 去哪找?  就不找了 默认返回undefined
    // 分析: 原型对象本身是一个对象(实例化对象)   Object.prototype = {}  也是构造函数创建的 => 是哪个构造创建的?    => 官方的纯对象数据 => 上级构造函数Object创建的 => 按照此种推论  => 出现了两个问题
    // a.  Object创建了 Object.prototype    2. Object.prototype上找不到 继续找创建它的构造函数的原型对象 =>Object.prototype (自己找自己 ) -> 停不下来(递归死查找)

    // 官方强制规定 Object.prototype的原型属性[[Prototype]] === null ,如果找不到就不找了 默认返回undefined

    // console.log(Object.prototype);

    // 证明一下 => 获取Object.prototype的原型属性[[Prototype]] 判断是否指向 null

    // console.log(Object.prototype.__proto__ === null);  // true
    // console.log(Object.getPrototypeOf(Object.prototype) === null); //true

    // 测试
    // console.log(Tom.aaa); // undefined
    // console.log(Tom.bbb); // undefined










</script>

</html>